package com.xq.controller;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.CircleCaptcha;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.google.common.base.CaseFormat;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.xq.annotation.RateLimit;
import com.xq.base.ResponseResult;
import com.xq.entity.TelephoneContact;
import com.xq.entity.UserInfo;
import com.xq.mapper.OrderMapper;
import com.xq.mapper.TelephoneContactMapper;
import com.xq.mapper.UserInfoMapper;
import com.xq.utils.MD5Sign;
import com.xq.vo.ChidaClinicMeberVo;
import com.xq.vo.DemoVo;
import com.xq.vo.SearchListVo;
import com.xq.vo.TableInfoVo;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest;
import tk.mybatis.mapper.entity.Example;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;
import java.util.concurrent.TimeUnit;

@RestController
public class TestContriller {


    @Autowired
    private TelephoneContactMapper telephoneContactMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private UserInfoMapper userInfoMapper;

    @RateLimit(rate = 1,rateInterval = 10,limiterKey = "createOrder_#{token}")
    @RequestMapping("createOrder")
    public ResponseResult test(@RequestHeader String token){
        Long productId =1L;
        try {
            Long pid = (Long) redisTemplate.opsForValue().get("kill_lock_" + productId);
            if(pid!=null){
                return ResponseResult.error(400,"获取锁失败");
            }
            redisTemplate.opsForValue().set("kill_lock_" + productId, productId);
            redisTemplate.expire("kill_lock_" + productId,2,TimeUnit.SECONDS);
            //查询商品
            //判断库存
            //插入订单
            //减库存
        }catch (Exception ex){
            ex.printStackTrace();
        }finally {
            redisTemplate.delete("kill_lock_" + productId);
        }

        //1.避免出现死锁，必须保证设置key和value和设置时间得原子性，lua脚本实现
        //2.锁过期，自动给未完成任务加时间问题，
        //我们一般用redission框架
        return ResponseResult.success();
    }

    @RequestMapping("cache")
    public ResponseResult cache(){
        List<UserInfo> list = Lists.newArrayList();
        UserInfo userInfo = new UserInfo();
        userInfo.setUserName("大宝");
        list.add(userInfo);
        redisTemplate.opsForValue().set("userList",list,1, TimeUnit.HOURS);
        List<UserInfo> userInfoList = (List<UserInfo> )redisTemplate.opsForValue().get("userList");
        return ResponseResult.success(userInfoList);
    }


    @RequestMapping("/list")
    public ResponseResult list(SearchListVo searchListVo){

        return ResponseResult.success();
    }

    @RequestMapping("/kill")
    public ResponseResult kill(Long productId,String token,int num){
        productId=101243L;
        String key ="sekill:"+productId;
        try {

            RSemaphore semaphore = redissonClient.getSemaphore(key);
           int a = semaphore.availablePermits();
           if(a<num){
               return ResponseResult.error("库存不足");
           }
            System.out.println(a);
            boolean semaphoreCount = semaphore.tryAcquire(num, 100, TimeUnit.MILLISECONDS);
            if(!semaphoreCount){
                return ResponseResult.error("秒杀失败");
            }
            System.out.println("下单");
        }catch (Exception ex){
            ex.printStackTrace();
        }
        return ResponseResult.success();
    }

    @RequestMapping("/stock")
    public ResponseResult s(){
        Long productId=101243L;

        String token = UUID.randomUUID().toString();
        String key = "sekill:"+token;
        RSemaphore semaphore = redissonClient.getSemaphore(key);
        semaphore.trySetPermits(50);
        return ResponseResult.success();
    }


    @RequestMapping("/captcha")
    public ResponseResult captcha() throws Exception {
        CircleCaptcha circleCaptcha = CaptchaUtil.createCircleCaptcha(300,100);
        String code = circleCaptcha.getCode();
        System.out.println(code);
        String token = IdUtil.randomUUID();
        redisTemplate.opsForValue().set(token,code,5,TimeUnit.MINUTES);
        Map map = Maps.newHashMap();
        map.put("token",token);
        map.put("imageBase64",circleCaptcha.getImageBase64());
       return ResponseResult.success(map);
    }

    @RequestMapping("/check")
    public ResponseResult check(String token,String code) throws Exception {
        if(StringUtils.isEmpty(token)){
            return ResponseResult.error(400,"token为空");
        }
        if(StringUtils.isEmpty(code)){
            return ResponseResult.error(400,"code为空");
        }
        String redisCode =  (String)redisTemplate.opsForValue().get(token);
        if(StringUtils.isEmpty(redisCode)){
            return ResponseResult.error(400,"验证码不存在");
        }
        if(!redisCode.equals(code)){
            redisTemplate.delete(token);
            return ResponseResult.error(400,"验证码错误");
        }
        return ResponseResult.success();
    }

    @RequestMapping("/test/order")
    public ResponseResult testOrder(@RequestBody DemoVo demoVo, HttpServletResponse response){
        response.setHeader("aaa",response.getHeader("111"));
        Map map = Maps.newHashMap();
        map.put("authState",1);
        System.out.println(JSON.toJSONString(demoVo));
        try {
            Thread.sleep(3000);
        }catch (Exception ex){
            ex.printStackTrace();
        }
        return ResponseResult.success();
    }

    @RequestMapping("/test/rest")
    public ResponseResult testRest(MultipartFile imageFile){
        System.out.println("数据："+imageFile);
        System.out.println("数据："+imageFile.getOriginalFilename());
        try {
            String str = HttpUtil.createPost("http://127.0.0.1:8080/api/common/ocr")
                    .form("merId","1001")
                    .form("sign","")
                    .form("imageFile", imageFile.getBytes(), imageFile.getOriginalFilename())
                    .execute().body();

            return ResponseResult.success(str);
        }catch (Exception ex){
            ex.printStackTrace();
        }
        return ResponseResult.success(null);
    }

    @PostMapping("/singleFile/upload")
    public ResponseResult singleFileUpLoad(@RequestParam("file") MultipartFile file) {
        //判断文件是否为空
        if(file.isEmpty()){
            return ResponseResult.error("文件为空");
        }
        //创建输入输出流
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            //指定上传的位置为 d:/upload/
            String path = "d:/upload/";
            //获取文件的输入流
            inputStream = file.getInputStream();
            String ext = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
            //获取上传时的文件名
            String fileName = UUID.randomUUID().toString().replace("-", "")+ext;
            //注意是路径+文件名
            File targetFile = new File(path + fileName);
            //判断文件父目录是否存在
            if(!targetFile.getParentFile().exists()){
                //不存在就创建一个
                targetFile.getParentFile().mkdir();
            }
            //获取文件的输出流
            outputStream = new FileOutputStream(targetFile);
            //最后使用资源访问器FileCopyUtils的copy方法拷贝文件
            FileCopyUtils.copy(inputStream, outputStream);
        } catch (IOException e) {
            e.printStackTrace();
            return ResponseResult.error("上传失败");
            //出现异常，则告诉页面失败
        } finally {
            //无论成功与否，都有关闭输入输出流
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return ResponseResult.success("上传成功");
    }


    @GetMapping("/test/db")
    public void  db() {
        TelephoneContact telephoneContact = new TelephoneContact();
        telephoneContact.setUserId(3L);
        List<TelephoneContact> list = telephoneContactMapper.select(telephoneContact);
        System.out.println(JSON.toJSONString(list));
    }

    @GetMapping("/tableInfo")
    public ResponseResult  tableInfo() {


        List<TableInfoVo>  list = orderMapper.selectTableInfoList("tb_order");
       Map<String,String> map = new HashMap<>();
        list.stream().forEach(c->{
          // String tableName = StringUtils.
            String resultStr = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, c.getColumnName());
            map.put(resultStr,c.getColumnComment());
        });


        return ResponseResult.success(map);
    }


    @GetMapping("/test/chida")
    public void  chida() {
        ChidaClinicMeberVo chidaClinicMeberVo1 = new ChidaClinicMeberVo();
        chidaClinicMeberVo1.setMemberLevel(0);
        chidaClinicMeberVo1.setExpireTime(new Date());
        chidaClinicMeberVo1.setClinicNo("C100126");
        ChidaClinicMeberVo chidaClinicMeberVo2 = new ChidaClinicMeberVo();
        chidaClinicMeberVo2.setMemberLevel(0);
        chidaClinicMeberVo2.setExpireTime(new Date());
        chidaClinicMeberVo2.setClinicNo("C100987");
        List<ChidaClinicMeberVo> list = Arrays.asList(chidaClinicMeberVo1,chidaClinicMeberVo2);
        userInfoMapper.updateBatchMember(list);
    }



    public static String underlineToCamel(String name) {
        name = name.trim();
        int len = name.length();
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c = name.charAt(i);
            if (c=='_') {
                if (++i < len) {
                    sb.append(Character.toUpperCase(name.charAt(i)));
                }
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }


}
